package com.ramnight.sql2.core;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class DbDriver {
	private static Logger logger = LoggerFactory.getLogger(DbDriver.class);
	private DataSource dataSource = null;
	
	private ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

	DbDriver(DataSource dataSource) {
		this.dataSource = dataSource;
		TABLE.init();
	}
	
	<T> T insert(String sql, Object... params){
		logger.debug("db execute => " + sql.replace("?", "'{}'"), params);
		
		try {
			Connection conn = threadLocal.get();
			if (conn == null) {
				return getRunner().insert(sql, new ScalarHandler<T>(), params);
			} else {
				return getRunner().insert(conn, sql, new ScalarHandler<T>(), params);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 更新（包括UPDATE、INSERT、DELETE，返回受影响的行数）
	int execute(String sql, Object... params) {
		logger.debug("db execute => " + sql.replace("?", "'{}'"), params);
		
		try {
			Connection conn = threadLocal.get();
			if (conn == null) {
				return getRunner().update(sql, params);
			} else {
				return getRunner().update(conn, sql, params);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
		return -1;
	}

	/**
	 * 返回第一行第一列的数据
	 */
	<T> T find(String sql, Object... params) {
		return search(sql, new ScalarHandler<T>(), params);
	}

	Map<String, Object> findMap(String sql, Object... params) {
		return search(sql, new MapHandler(), params);
	}

	List<Map<String, Object>> searchMapList(String sql, Object... params) {
		return search(sql, new MapListHandler(), params);
	}

	<T> List<T> searchList(String sql, Object... params) {
		return search(sql, new ColumnListHandler<T>(), params);
	}

	/**
	 * 第一列为键值
	 */
	<T> Map<T, Map<String, Object>> searchKeyMap(String sql, Object... params) {
		return search(sql, new KeyedHandler<T>(), params);
	}

	private <T> T search(String sql, ResultSetHandler<T> handler, Object... params) {
		logger.debug("db query => " + sql.replace("?", "'{}'"), params);
		try {
			Connection conn = threadLocal.get();
			if (conn == null) {// 传入connection，则不自动关闭connection
				return getRunner().query(sql, handler, params);
			} else {
				return getRunner().query(conn, sql, handler, params);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	Connection startTransaction() {
		try {
			Connection conn = threadLocal.get();
			if (conn == null) {
				conn = getConnection();
				conn.setAutoCommit(false);
				threadLocal.set(conn);
				return conn;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	void closeTransaction(){
		try {
			Connection conn = threadLocal.get();
			if (conn != null) {
				conn.setAutoCommit(true);
				conn.close();
				threadLocal.remove();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	DataSource getDataSource() throws SQLException {
		return dataSource;
	}

	Connection getConnection() throws SQLException {
		return dataSource.getConnection();
	}
	
	QueryRunner getRunner(){
		return new QueryRunner(this.dataSource);
	}
}
